﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Threading;
using System.Web;
using BattleThis.RavenDB;
using BattleThis.Core;
using System.Web.Mvc;

namespace BattleThis
{
		public class PersistenceContext 
		{

			#region Variablen
			private static PersistenceContext m_Instance = new PersistenceContext();
			private const string HTTPCONTEXTKEY = "Repository.Base.HttpContext.Key";
			private static readonly Hashtable m_Threads = new Hashtable();
			#endregion

			#region Properties

			public static PersistenceContext Current
			{
				get { return m_Instance; }
			}

			public IUnitOfWork UnitOfWork
			{
				get
				{
					var unitOfWork = GetUnitOfWork();

					if( unitOfWork == null )
					{
						unitOfWork = this.CreateUnitOfWork();
					}

					return unitOfWork;
				}
			}

			public void Clear()
			{
				this.UnitOfWork.Dispose();
				this.RemoveUnitOfWork();
			}

			#endregion

			#region Methoden

			protected void RemoveUnitOfWork()
			{
				if( HttpContext.Current != null )
				{
					HttpContext.Current.Items.Remove( HTTPCONTEXTKEY );
				}
				else
				{
					lock( m_Threads.SyncRoot )
					{
						m_Threads.Remove( Thread.CurrentThread.Name );
					}
				}
			}

			protected IUnitOfWork CreateUnitOfWork()
			{
					var unitOfWorkFactory =	DependencyResolver.Current.GetService<IUnitOfWorkFactory>();
					var unitOfWork = unitOfWorkFactory.Create();

					SaveUnitOfWork( unitOfWork );

					return unitOfWork;
			}

			protected IUnitOfWork GetUnitOfWork()
			{
				if( HttpContext.Current != null )
				{
					if( HttpContext.Current.Items.Contains( HTTPCONTEXTKEY ) )
					{
						return (IUnitOfWork)HttpContext.Current.Items[ HTTPCONTEXTKEY ];
					}

					return null;
				}
				else
				{
					Thread thread = Thread.CurrentThread;
					if( string.IsNullOrEmpty( thread.Name ) )
					{
						thread.Name = Guid.NewGuid().ToString();
						return null;
					}
					else
					{
						lock( m_Threads.SyncRoot )
						{
							return (IUnitOfWork)m_Threads[ Thread.CurrentThread.Name ];
						}
					}
				}
			}

			protected void SaveUnitOfWork( IUnitOfWork unitOfWork )
			{
				if( HttpContext.Current != null )
				{
					HttpContext.Current.Items[ HTTPCONTEXTKEY ] = unitOfWork;
				}
				else
				{
					lock( m_Threads.SyncRoot )
					{
						m_Threads[ Thread.CurrentThread.Name ] = unitOfWork;
					}
				}
			}

			#endregion

		}
}
